package com.project.common.core.utils.zxing;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.project.common.core.config.prop.PropAttributes;
import com.project.common.core.config.prop.PropConfig;
import com.project.common.core.utils.exception.BaseCustomException;
import com.project.common.core.utils.file.FilePathConsts;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 条形码工具类
 */
public class LineCodeUtil {

    private static Logger log = LoggerFactory.getLogger(LineCodeUtil.class);

    /**
     * 创建条形码
     *
     * @param content 条形码内容
     * @param width   宽度
     * @param height  高度
     * @param imgPath 条形码图片路径
     * @return
     */
    public static void createLineCode(String content, int width, int height, String imgPath) throws BaseCustomException {

        int codeWidth = 3 + // start guard
                (7 * 6) + // left bars
                5 + // middle guard
                (7 * 6) + // right bars
                3; // end guard

        codeWidth = Math.max(codeWidth, width);

        Graphics2D graphics2D = null;
        ImageOutputStream imageOutputStream = null;
        ImageWriter imageWriter = null;
        int lineCodeHeight = height - 20;

        try {
            //获取图片存储的临时目录
            String tmpPath = PropConfig.getProperty(PropAttributes.NFS__SERVICE_FILE_TEMP_PATH) + "/" + FilePathConsts.FILE_QR_PATH +"/"+ System.currentTimeMillis() + ".png";

            //生成条形码临时图片
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content,
                    BarcodeFormat.CODE_128, codeWidth, lineCodeHeight, null);
            MatrixToImageWriter.writeToStream(bitMatrix, "png",
                    new FileOutputStream(tmpPath));

            File srcFile = new File(tmpPath);
            File destFile = new File(imgPath);

            FileUtils.copyFile(srcFile, destFile);
            BufferedImage srcBufferedImage = ImageIO.read(srcFile);
            int topSpace = 8;//顶部空间
            int bottomSpace = 2;//底部空间
            BufferedImage destBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            graphics2D = destBufferedImage.createGraphics();

            //设置属性，并绘制图形
            graphics2D.setBackground(Color.white);
            graphics2D.clearRect(0, 0, width, height);
            graphics2D.drawImage(srcBufferedImage, 0, topSpace, null);
            graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP));

            //设置字体颜色并在图形上添加字体
            graphics2D.setColor(Color.BLACK);
            FontMetrics fontMetrics = graphics2D.getFontMetrics();
            int fontsWidth = fontMetrics.stringWidth(content);//获取字符串内容宽度
            int fontsX = (width - fontsWidth) / 2;//获取字体X坐标
            fontsX = fontsX < 0 ? 0 : fontsX;
            graphics2D.drawString(content, fontsX, height - bottomSpace);

            //将图形写入到目标文件
            imageOutputStream = ImageIO.createImageOutputStream(destFile);
            imageWriter = ImageIO.getImageWritersByFormatName(FilenameUtils.getExtension(destFile.getName())).next();
            imageWriter.setOutput(imageOutputStream);
            ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();
            imageWriter.write(null, new IIOImage(destBufferedImage, null, null), imageWriteParam);
            imageOutputStream.flush();

        } catch (Exception e) {
            log.error("创建条形码失败: " + ExceptionUtils.getFullStackTrace(e));
            throw new BaseCustomException("createBarCodeError", "创建条形码失败");
        } finally {
            if (graphics2D != null) {
                graphics2D.dispose();
            }
            if (imageWriter != null) {
                imageWriter.dispose();
            }
            if (imageOutputStream != null) {
                try {
                    imageOutputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * 解析条形码
     *
     * @param imgPath 图片路径
     * @return
     */
    public static String parseLineCode(String imgPath) {
        BufferedImage image = null;
        Result result = null;
        try {
            image = ImageIO.read(new File(imgPath));
            if (image == null) {
                log.error("解析的条形码文件不存在！");
                return null;
            }
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            result = new MultiFormatReader().decode(bitmap, null);
            return result.getText();
        } catch (Exception e) {
            log.error("条形码解析发生错误： " + ExceptionUtils.getFullStackTrace(e));
        }
        return null;
    }

}
